#!/usr/bin/env python
# -*- coding:utf-8 -*-
import sys

sys.path.append('..')
from common_utils import CBBCommonUtils


def get_plugin_info():
    plugin_info = {
        "name": "centos_access_control_022 Turn_off_system_trust_mechanism",
        "plugin_id": "centos_access_control_022",
        "plugin_type": "Access Control",
        "info": "Check and delete hosts.equiv, .rhosts and .netrc to turn off system trust mechanism",
        "level": "C",
        "module": "Safety reinforcement",
        "author": "fanyi",
        "keyword": "Safety reinforcement",
        "configable": "false"
    }
    return plugin_info

file_list = ["hosts.equiv", ".rhosts", ".netrc"]

logger = None
cur_user = None
cur_module = None
cur_task = None


def set_plugin_logger(setter, user, module, task, *args, **kwargs):
    global logger, cur_user, cur_module, cur_task
    logger = setter
    cur_user = user
    cur_module = module
    cur_task = task


# 扫描函数
def scan(ip, sys_user, sys_pwd, flag=0):
    des_list = []
    error_count = 0
    flag_list = []
    logger.debug_info(cur_user, cur_module, cur_task+'_Scan', '', "Scan Start.")
    for i, item in enumerate(file_list):
        # 获取当前状态
        cmd = "find / -maxdepth 3 -name " + item + " 2>/dev/null"
        result, output = CBBCommonUtils.cbb_run_cmd(ip, cmd, username=sys_user, passwd=sys_pwd)
        # 检错，每次执行命令都会进行检错，并决定返回退出/继续执行
        if not result and len(output) == 0:
            des_list.append(item + " safe")
            logger.debug_info(cur_user, cur_module, cur_task+'_Scan', '', item + " is safe.")
        elif not result and len(output) != 0:
            error_count += 1
            des_list.append(item + " not disabled")
            logger.debug_warning(cur_user, cur_module, cur_task+'_Scan', '', item + " not disabled.")
            flag_list.append(output[0].replace("\n", ""))
        else:
            error_des = "CMD process ERROR. Error info: {}".format(result[0].replace("\n", ""))
            des_list.append(error_des)
            logger.debug_error(cur_user, cur_module, cur_task+'_Scan', '', error_des)
            error_count += 1
            return des_list, error_count
    des_list.append("Scan Complete.")
    logger.debug_info(cur_user, cur_module, cur_task+'_Scan', '', "Scan Complete.")
    # 是否加固
    if flag == 1 and len(flag_list) != 0:
        reinforce_des, reinforce_err = reinforce(ip, sys_user, sys_pwd, flag_list)
        if reinforce_err == 0:
            error_count = 0
            des_list.extend(reinforce_des)
        else:
            error_count += 1
            des_list.extend(reinforce_des)
    return des_list, error_count


# 加固函数
def reinforce(ip, sys_user, sys_pwd, flag_list):
    des_list = []
    error_count = 0
    logger.debug_info(cur_user, cur_module, cur_task+'_Reinforce', '', "Reinforce Start.")
    for item in flag_list:
        safe_cmd = "mv " + item + " " + item + ".bak"
        result, output = CBBCommonUtils.cbb_run_cmd(ip, safe_cmd, username=sys_user, passwd=sys_pwd)
        if not result:
            # 检查
            check_cmd = "ls " + item + ".bak"
            result, output = CBBCommonUtils.cbb_run_cmd(ip, check_cmd, username=sys_user, passwd=sys_pwd)
            if not result and len(output) != 0:
                des_list.append(item + " Reinforce Complete.")
                logger.debug_info(cur_user, cur_module, cur_task+'_Reinforce', '', item + " Reinforce Complete.")
            else:
                error_count += 1
                des_list.append("Reinforce ERROR")
                logger.debug_error(cur_user, cur_module, cur_task+'_Reinforce', '', "Reinforce Error.")
                # 加固失败，回滚
                rollback_des, rollback_err = rollback(ip, sys_user, sys_pwd)
                if rollback_err == 0:
                    des_list.extend(rollback_des)
                else:
                    error_count += 1
                    des_list.extend(rollback_des)
                return des_list, error_count
        else:
            error_count += 1
            des_list.append("Reinforce Failed.")
            logger.debug_error(cur_user, cur_module, cur_task+'_Reinforce', '', "Reinforce Failed.")
            # 加固失败，回滚
            rollback_des, rollback_err = rollback(ip, sys_user, sys_pwd)
            if rollback_err == 0:
                des_list.extend(rollback_des)
            else:
                error_count += 1
                des_list.extend(rollback_des)
            return des_list, error_count
    des_list.append("Reinforce Complete.")
    logger.debug_info(cur_user, cur_module, cur_task+'_Reinforce', '', "Reinforce Complete.")
    return des_list, error_count


# 回滚函数
def rollback(ip, sys_user, sys_pwd):
    des_list = []
    error_count = 0
    logger.debug_info(cur_user, cur_module, cur_task+'_Rollback', '', "Rollback Start.")
    for i, item in enumerate(file_list):
        # 获取当前状态
        cmd = "find / -maxdepth 3 -name " + item + ".bak 2>/dev/null"
        result, output = CBBCommonUtils.cbb_run_cmd(ip, cmd, username=sys_user, passwd=sys_pwd)
        # 检错，每次执行命令都会进行检错，并决定返回退出/继续执行
        if not result and len(output) == 0:
            des_list.append(item + ".bak not found")
            logger.debug_info(cur_user, cur_module, cur_task+'_Scan', '', item + ".bak not found")
        elif not result and len(output) != 0:
            logger.debug_info(cur_user, cur_module, cur_task+'_Scan', '', item + ".bak found")
            len_tar = len(output[0].replace("\n", "")) - 4
            tar = output[0][:len_tar]
            cmd = "mv " + output[0] + " " + tar
            # 回滚文件
            result, output = CBBCommonUtils.cbb_run_cmd(ip, cmd, username=sys_user, passwd=sys_pwd)
            if not result:
                restart_cmd = "ls " + tar
                result, output = CBBCommonUtils.cbb_run_cmd(ip, restart_cmd, username=sys_user, passwd=sys_pwd)
                if not result and len(output) != 0:
                    des_list.append(item + " Rollback Complete.")
                    logger.debug_info(cur_user, cur_module, cur_task+'_Rollback', '', item + " Rollback Complete.")
                else:
                    error_count += 1
                    des_list.append("Rollback check error.")
                    logger.debug_error(cur_user, cur_module, cur_task+'_Rollback', '', "Rollback check error.")
                    return des_list, error_count
            else:
                error_count += 1
                des_list.append("Rollback Failed.")
                logger.debug_error(cur_user, cur_module, cur_task+'_Rollback', '', "Rollback Failed.")
                return des_list, error_count
        else:
            error_des = "CMD process ERROR. Error info: {}".format(result[0].replace("\n", ""))
            des_list.append(error_des)
            logger.debug_error(cur_user, cur_module, cur_task+'_Scan', '', error_des)
            error_count += 1
            return des_list, error_count
    des_list.append("Rollback Complete.")
    logger.debug_info(cur_user, cur_module, cur_task+'_Rollback', '', "Rollback Complete.")
    return des_list, error_count


def check(ip, *args, **kwargs):
    sys_user = kwargs.get("system_user")
    sys_pwd = kwargs.get("system_pwd")
    comm = kwargs.get("command")
    try:
        des_list = []
        logger.debug_info(cur_user, cur_module, cur_task+'_Check', '', "centos_access_control_022 Start")
        if comm == 1:
            des_scan, error_scan = scan(ip, sys_user, sys_pwd, flag=0)
            des_list.extend(des_scan)
            step_error = int(error_scan)
        elif comm == 2:
            des_reinforce, error_reinforce = scan(ip, sys_user, sys_pwd, flag=1)
            des_list.extend(des_reinforce)
            step_error = int(error_reinforce)
        elif comm == 3:
            des_rollback, error_rollback = rollback(ip, sys_user, sys_pwd)
            des_list.extend(des_rollback)
            step_error = int(error_rollback)
        else:
            return {"code": 3, "count": 0, "des": ['command must be 1/2/3']}
        logger.debug_info(cur_user, cur_module, cur_task+'_Check', '', "centos_access_control_022 Complete")
        if step_error == 0:
            code = 0
        elif step_error <= -1:
            code = 2
        else:
            code = 1
        return {"code": code, "count": step_error, "des": des_list}
    except Exception as er:
        code = 1
        des = ["ERROR:", str(er)]
        logger.debug_error(cur_user, cur_module, cur_task+'_Check', '', des)
        return {"code": code, "count": 0, "des": des}


#check(ip="100.2.91.150", system_user="root", system_pwd="admin", command=0, flag=0)
